package utils

import (
	"io"
	"os"
	"path/filepath"
	"regexp"
	"strings"
)

/**
 * @brief:  批量移动文件
 * @param:  files: 文件列表
 * @param:  dest: 目标文件夹
 * @detail: 比如: MoveFiles([]string{"a.txt", "b.txt"}, "a/")
 */
func MoveFiles(files []string, destDir string) {
	dest, err := os.Stat(destDir)
	if err != nil {
		//如果目标文件夹不存在，则创建
		if os.IsNotExist(err) {
			err := os.MkdirAll(destDir, 0775)
			if err != nil {
				panic(err)
			}
			dest, err = os.Stat(destDir)
		} else {
			panic(err)
		}
	}
	if err != nil {
		panic(err)
	}
	if dest.IsDir() { // 是文件夹
		for _, file := range files {
			//获取最后的路径分隔符下标
			index := strings.LastIndex(file, string(os.PathSeparator))
			//获取文件夹名称
			dirName := file[index+1:]
			err := os.Rename(file, filepath.Join(destDir, dirName))
			if err != nil {
				panic(err)
			}
		}
	}

}

/**
 * @brief:  批量复制文件
 * @param:  files: 文件列表
 * @param:  dest: 目标文件夹
 * @detail: 比如: CopyFiles([]string{"a.txt", "b.txt"}, "a")
 */
func CopyFiles(files []string, destDir string) {
	dest, err := os.Stat(destDir)
	if err != nil {
		//如果目标文件夹不存在，则创建
		if os.IsNotExist(err) {
			err := os.MkdirAll(destDir, 0775)
			if err != nil {
				panic(err)
			}
			dest, err = os.Stat(destDir)
		} else {
			panic(err)
		}
	}
	if dest.IsDir() { // 是文件夹
		for _, file := range files {
			oldFile, err := os.Open(file)
			if err != nil {
				panic(err)
			}
			defer oldFile.Close()
			//判断是否是文件夹
			fileInfo, err := oldFile.Stat()
			if fileInfo.IsDir() {
				var files1 []string
				GetFiles(file, &files1, true)
				//获取最后的路径分隔符下标
				index := strings.LastIndex(file, string(os.PathSeparator))
				//获取文件夹名称
				dirName := file[index+1:]
				CopyFiles(files1, destDir+string(os.PathSeparator)+dirName)
				return
			}
			fileName := filepath.Base(file)
			destFile, _ := os.OpenFile(filepath.Join(destDir, fileName), os.O_RDWR|os.O_CREATE, 0775)
			defer destFile.Close()
			// 读写取文件内容
			buf := make([]byte, 2048)
			for {
				n, err := oldFile.Read(buf)
				if err == io.EOF {
					break
				}
				destFile.Write(buf[:n])
			}
		}
	}
}

/**
 * @brief:  获取指定文件夹下的所有文件(包括子文件夹)
 * @param:  dir: 文件夹路径
 * @param:  files: 文件列表
 * @param:  model: 是否包含子文件夹路径,如果为true,则包含子文件夹路径,否则不包含,但是子文件夹下的文件会包含
 * @return: []string: 文件列表
 *@detail: 比如: GetFiles("a/")
 */
func GetFiles(dir string, files *[]string, model bool) {

	file, err := os.Open(dir)
	if err != nil {
		panic(err)
	}
	defer file.Close()
	fileInfos, err := file.Readdir(-1)
	if err != nil {
		panic(err)
	}
	for _, fileInfo := range fileInfos {
		if fileInfo.IsDir() {
			if model {
				*files = append(*files, filepath.Join(dir, fileInfo.Name()))
			}
			GetFiles(dir+string(os.PathSeparator)+fileInfo.Name(), files, model)
		} else {
			*files = append(*files, filepath.Join(dir, fileInfo.Name()))
		}
	}
}

/**
 * @brief:  获取指定文件夹下的所有文件,不包含子文件夹下文件
 * @param:  dir: 文件夹路径
 * @param:  files: 文件列表
 * @param:  model: 是否包含子文件夹路径,如果为true,则包含子文件夹路径,否则不包含
 * @return: []string: 文件列表
 *@detail: 比如: GetFile("a/")
 */
func GetFile(dir string, files *[]string, model bool) {
	file, err := os.Open(dir)
	if err != nil {
		panic(err)
	}
	defer file.Close()
	fileInfos, err := file.Readdir(-1)
	if err != nil {
		panic(err)
	}
	for _, fileInfo := range fileInfos {
		if fileInfo.IsDir() {
			if model {
				*files = append(*files, filepath.Join(dir, fileInfo.Name()))
			}
			continue
		} else {
			*files = append(*files, filepath.Join(dir, fileInfo.Name()))
		}
	}
}

/**
 * @brief:  获取当前项目根目录
 * @param:  projectName: 项目名称
 * @return: string: 项目根目录
 * @detail: 比如: GetCurrentDirectory("go-utils") -> F:\go-project\go-utils
 */
func GetCurrentDirectory(projectName string) string {
	dir, err := os.Getwd()
	if err != nil {
		panic(err)
	}
	//正则表达式截取项目根目录
	reg := regexp.MustCompile(`(.*)` + projectName)
	return filepath.Join(reg.FindStringSubmatch(dir)[1], projectName)
}

/**
 * @brief:  搜索指定文件夹下的满足条件的文件
 * @param:  dir: 文件夹路径
 * @param:  files: 文件列表
 * @param:  reg: 正则表达式
 */
func SearchFiles(dir string, files *[]string, reg *regexp.Regexp) {

	file, err := os.Open(dir)
	if err != nil {
		panic(err)
	}
	defer file.Close()
	fileInfos, err := file.Readdir(-1)
	if err != nil {
		panic(err)
	}
	for _, fileInfo := range fileInfos {
		if fileInfo.IsDir() {
			SearchFiles(filepath.Join(dir, fileInfo.Name()), files, reg)
		} else {
			if reg.MatchString(fileInfo.Name()) {
				*files = append(*files, filepath.Join(dir, fileInfo.Name()))
			}
		}
	}
}
